
#include "uart_pl01x_dev.h"

static struct pl011_uart uart;
static struct pl011_uart *seria_port;

#define UART_PL01x_FR_RXFE              0x10
#define UART_PL01x_FR_TXFF              0x20

void _pl01x_init(void *uart_base_addr, int baud_divisor)
{
    seria_port = (struct pl011_uart*)uart_base_addr;

    /*
     * ensure the UART is disabled
     */
    uart.UARTCR  = 0x0;

    /*
     * OK, now program this thing up
     */
    uart.UARTECR   = 0x0;  // Clear the receive status (i.e. error) register
    uart.UARTLCR_H = 0x0 | PL011_LCR_WORD_LENGTH_8 | PL011_LCR_FIFO_DISABLE | \
                     PL011_LCR_ONE_STOP_BIT | PL011_LCR_PARITY_DISABLE | PL011_LCR_BREAK_DISABLE;

    // uart.UARTIBRD = PL011_IBRD_DIV_38400;
    // uart.UARTFBRD = PL011_FBRD_DIV_38400;

    uart.UARTIBRD = baud_divisor;
    uart.UARTFBRD = baud_divisor;

    /*
     * mask and clear all interrupts
     */
    uart.UARTIMSC = 0x0;
    uart.UARTICR  = PL011_ICR_CLR_ALL_IRQS;

    uart.UARTCR  = 0x0 | PL011_CR_UART_ENABLE | PL011_CR_TX_ENABLE | PL011_CR_RX_ENABLE;

    seria_port->UARTCR = uart.UARTCR;
    seria_port->UARTECR = uart.UARTECR;
    seria_port->UARTLCR_H = uart.UARTLCR_H;
    seria_port->UARTIBRD = uart.UARTIBRD;
    seria_port->UARTFBRD = uart.UARTFBRD;
    seria_port->UARTIMSC = uart.UARTIMSC;
    seria_port->UARTICR = uart.UARTICR;
    seria_port->UARTCR = uart.UARTCR;
    return;
}

void _pl01x_putc(const char c)
{
    while (seria_port->UARTFR & UART_PL01x_FR_TXFF);
    seria_port->UARTDR = c;
    if (c == '\n')
        seria_port->UARTDR = '\r';
}

char _pl01x_getc()
{
    unsigned int data;
    while (seria_port->UARTFR & UART_PL01x_FR_RXFE);
    return seria_port->UARTDR;
}

